package cn.onein.edu.util;

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.Iterator;
import java.util.Map;
import java.util.ResourceBundle;
import java.util.Set;
import java.util.SortedMap;
import java.util.TreeMap;

import cn.onein.edu.common.PaymentType;

public class PaymentRequestHandler {
	private static final String CHARSET;
	private static final String SIGN_TYPE;
	
	private static final String TENPAY_GATE_URL;	
	private static final String TENPAY_PARTNER;
	private static final String TENPAY_KEY;
	
	private static final String ALIPAY_GATE_URL;
	private static final String ALIPAY_PARTNER;
	private static final String ALIPAY_KEY;
	private static final String ALIPAY_SELLER_EMAIL;
	
	static{
		ResourceBundle paymentInfo = ResourceUtil.getPaymentProperties();
		
		CHARSET = paymentInfo.getString("CHARSET");
		
		SIGN_TYPE= paymentInfo.getString("SIGN_TYPE");
		
		TENPAY_GATE_URL = paymentInfo.getString("TENPAY_GATE_URL");
		TENPAY_PARTNER = paymentInfo.getString("TENPAY_PARTNER");
		TENPAY_KEY = paymentInfo.getString("TENPAY_KEY");
		
		ALIPAY_GATE_URL = paymentInfo.getString("ALIPAY_GATE_URL");
		ALIPAY_PARTNER = paymentInfo.getString("ALIPAY_PARTNER");
		ALIPAY_KEY = paymentInfo.getString("ALIPAY_KEY");
		ALIPAY_SELLER_EMAIL = paymentInfo.getString("ALIPAY_SELLER_EMAIL");
	}
	
	/** 请求的参数 */
	private SortedMap<String,String> params = new TreeMap<String,String>();
	
	private PaymentType paymentType = null;
	
	private String gateUrl = null;
	
	private String key = null;
	
	private String debugInfo = null;
	
	private PaymentRequestHandler(){}	
	
	public static PaymentRequestHandler getInstance(PaymentType type){
		if(type == null){
			throw new IllegalArgumentException("PaymentType must be not null!");
		}
		
		PaymentRequestHandler handler = new PaymentRequestHandler();

		handler.paymentType = type;
		
		return handler;
	}
	
	public String getRequestURL() throws UnsupportedEncodingException {
		String signedUrl = null;
		
		switch(paymentType){
		case Tenpay:
			gateUrl = TENPAY_GATE_URL;
			this.setParam("partner", TENPAY_PARTNER);
			key = TENPAY_KEY;
			signedUrl = getSignedUrl();
			break;
		case Alipay:
			gateUrl = ALIPAY_GATE_URL;
			this.setParam("partner", ALIPAY_PARTNER);
			this.setParam("seller_email", ALIPAY_SELLER_EMAIL);
			this.setParam("_input_charset", CHARSET);
			
			key = ALIPAY_KEY;
			signedUrl = getSignedUrl();
			break;
		default:
			break;
		}
		
		return signedUrl;
	}
	
	public PaymentType getPaymentType(){
		return paymentType;
	}
	
	public String getDebugInfo(){
		return debugInfo;
	}
	
	/**
	 * 设置支付参数，注意商户号和KEY，还有Gate Url不用设置！
	 * @param key
	 * @param value
	 */
	public void setParam(String key, String value){
		if(key != null && value != null){
			String v = "";
			v = value.trim();
			this.params.put(key, v);			
		}
	}
	
	public String getParam(String key){
		String value = params.get(key);
		return value == null ? "" : value;
	}
	
	/**
	 * 获取带参数的请求URL
	 * @return String
	 * @throws UnsupportedEncodingException 
	 */
	private String getSignedUrl() throws UnsupportedEncodingException {
		String reqPars = "";
			
		this.createSign();
		
		StringBuffer sb = new StringBuffer();
		
		Set es = this.params.entrySet();
		Iterator it = es.iterator();
		while(it.hasNext()) {
			Map.Entry entry = (Map.Entry)it.next();
			String k = (String)entry.getKey();
			String v = (String)entry.getValue();
			sb.append(k + "=" + URLEncoder.encode(v, CHARSET) + "&");
		}
		
		switch(paymentType){
		case Tenpay:
			//去掉最后一个&
			reqPars = sb.substring(0, sb.lastIndexOf("&"));
			break;
		case Alipay:
			sb.append("sign_type=" + SIGN_TYPE);
			reqPars = sb.toString();
			break;
		default:
			break;			
		}
		
		return gateUrl + "?" + reqPars;		
	}

	/**
	 * 创建md5摘要,规则是:按参数名称a-z排序,遇到空值的参数不参加签名。
	 * 
	 * sign = Md5(原字符串&key=商户密钥).toUpperCase
	 */
	private void createSign() {
		StringBuffer sb = new StringBuffer();
		String sign = "";
		Set es = this.params.entrySet();
		Iterator it = es.iterator();
		while(it.hasNext()) {
			Map.Entry entry = (Map.Entry)it.next();
			String k = (String)entry.getKey();
			String v = (String)entry.getValue();
			if(null != v && !"".equals(v) 
					&& !"sign".equals(k) && !"key".equals(k)) {
				sb.append(k + "=" + v + "&");
			}
		}
		
		switch(paymentType){
		case Tenpay:
			sb.append("key=" + key);
			sign = PaymentUtil.MD5Encode(sb.toString(), CHARSET).toUpperCase();
			break;
		case Alipay:
			sign = sb.substring(0, sb.lastIndexOf("&"));
			sign = sign + key;
			sign = PaymentUtil.MD5Encode(sign, CHARSET);
			break;
		default:
			break;			
		}
		
		this.setParam("sign", sign);
		
		//debug信息
		this.debugInfo = sb.toString() + " => sign:" + sign;		
	}
}
